package com.wei.test.Service.Impl;

import com.wei.test.Service.RediService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.concurrent.TimeUnit;

@Service
public class RediServiceImpl implements RediService {

    private static final int DEFAULT_ACQUIRY_RESOLUTION_MILLIS = 100;
    @Autowired
    private RedisTemplate redisTemplate;

    public boolean set(final String key, Object value) {
        boolean result = false;

        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    public boolean set(final String key, Object value, Long expireTime) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public void remove(final String key) {
        if (exists(key)) {
            redisTemplate.delete(key);
        }
    }

    public boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    public Object get(final String key) {
        Object result = null;
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        result = operations.get(key);
        return result;
    }

    public boolean setNX(final String key, final String value) {
        boolean result = false;
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        result = operations.setIfAbsent(key, value);
        return result;
    }

    public Object getSet(final String key, final String value) {
        Object result = null;
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        result = operations.getAndSet(key, value);
        return result;
    }

    public boolean lock(String lockKey) throws InterruptedException {
        return lock(lockKey, 6 * 1000, 3 * 1000);
    }

    public boolean lock(String lockKey, int timeoutMsecs, int expireMsecs) throws InterruptedException {
        while (timeoutMsecs >= 0) {
            long expires = System.currentTimeMillis() + expireMsecs + 1;
            String expiresStr = String.valueOf(expires);

            if (this.setNX(lockKey, expiresStr))
                return true;

            Object currentValueObj = get(lockKey);
            if (currentValueObj != null) {
                String currentValueStr = currentValueObj.toString();
                if (Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
                    String oldValueStr = getSet(lockKey, expiresStr).toString();

                    if (oldValueStr != null && oldValueStr.equals(currentValueStr))
                        return true;
                }
            }

            timeoutMsecs -= DEFAULT_ACQUIRY_RESOLUTION_MILLIS;
            Thread.sleep(DEFAULT_ACQUIRY_RESOLUTION_MILLIS);
        }
        return false;
    }

    public void unlock(String lockKey) {
        remove(lockKey);
    }

//    public void hmSet(String key, Map value){
//        HashOperations hashOperations = redisTemplate.opsForHash();
//        hashOperations.putAll(key, value);
//    }
//
//    public Map hmGet(String key){
//        HashOperations hashOperations = redisTemplate.opsForHash();
//        return hashOperations.entries(key);
//    }
//
//    public void lPush(String k,Object v){
//        ListOperations<String, Object> list = redisTemplate.opsForList();
//        list.rightPush(k,v);
//    }
//
//    public List<Object> lRange(String k, long l, long l1){
//        ListOperations<String, Object> list = redisTemplate.opsForList();
//        return list.range(k,l,l1);
//    }
//
//    public long lSize(String key) {
//        ListOperations<String, Object> list = redisTemplate.opsForList();
//        return list.size();
//    }

}
      
           
      

